package java8;

import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/7/19 15:41
 * <p>
 * 终止操作
 */
public class TestStreamAPI3 {
    /**
     * 查找与匹配
     * allMatch--检查是否匹配所有元素
     * anyMatch--检查是否至少匹配一个元素
     * noneMatch--检查是否没有匹配的元素
     * findFirst--返回第一个匹配的元素
     * findAny--返回当前流中任意匹配的元素
     * count--返回流中元素的总个数
     * max--返回流中最大值
     * min--返回流中最小值
     */
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99, Employee.Status.FREE),
            new Employee("李四", 38, 5555.555, Employee.Status.BUSY),
            new Employee("王五", 50, 6666.66, Employee.Status.VOCATION),
            new Employee("赵柳", 16, 3333.33, Employee.Status.FREE),
            new Employee("田七", 8, 7777.77, Employee.Status.BUSY));

    @Test
    public void test1() {
        boolean b1 = employees.stream().allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);

        boolean b2 = employees.stream().anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);

        boolean b3 = employees.stream().noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b3);

        Optional<Employee> op1 = employees.stream().sorted(Comparator.comparingDouble(Employee::getSalary)).findFirst();

        System.out.println(op1.get());

        Optional<Employee> op2 = employees.parallelStream().filter(e -> e.getStatus().equals(Employee.Status.FREE)).findAny();
        System.out.println(op2.get());
    }

    @Test
    public void test2() {
        Long count = employees.stream().count();
        System.out.println(count);

        Optional<Employee> op1 = employees.stream().max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(op1.get());

        Optional<Double> op2 = employees.stream().map(Employee::getSalary).min(Double::compare);
        System.out.println(op2.get());

    }

    /**
     * 规约: 可以将流中元素反复结合起来，得到一个值
     */
    @Test
    public void test3() {
        List<Integer> list = Arrays.asList(2, 2, 3, 4, 5, 6, 2, 7, 8, 9, 10);
        Integer sum = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(sum);

        System.out.println("-----------------");

        Optional<Double> op = employees.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(op.get());
    }

    /**
     * 收集
     */
    @Test
    public void test4() {
        List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());
        list.forEach(System.out::println);

        System.out.println("------------------------");

        Set<String> set = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
        set.forEach(System.out::println);
    }

    @Test
    public void test5() {
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);

        // 平均值
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);

        // 总和
        Double sum = employees.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);

        // 最大值
        Optional<Employee> max = employees.stream().max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(max.get().toString());

        // 最小值
        Optional<Double> min = employees.stream()
                .map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());
    }

    // 分组
    @Test
    public void test6() {
        Map<Employee.Status, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));

        System.out.println(map);

    }

    // 多级分组
    @Test
    public void test7() {
        Map<Employee.Status, Map<Object, List<Employee>>> mp = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(e -> {
                    if (((Employee) e).getAge() <= 35) {
                        return "青年";
                    } else if (((Employee) e).getAge() <= 50) {
                        return "中年";
                    } else {
                        return "老年";
                    }
                })));

        System.out.println(mp);
    }

    //
}
